package com.card.game.pdk;

import java.util.List;
import java.util.Random;
import java.util.Vector;

import com.card.common.CardContants;
import com.card.common.MessageComm;
import com.card.game.BasePlayer;
import com.card.game.Card;
import com.card.game.CardUtils;
import com.card.game.Player;
import com.card.game.playback.PlayBackManager;
import com.card.game.room.AbstractRoom;
import com.card.game.room.RoomState;
import com.card.message.JsonMessageCenter;
import com.card.user.UserBack;
import com.google.common.collect.Lists;
import com.google.common.escape.Escaper;
import com.xiaoao.net.common.GameConstants;
import com.xiaoao.net.json.message.JsonMessage;
import com.xiaoao.net.utils.StringUtil;
import com.xiaoao.net.utils.json.GSONUtils;

public class PdkRoom extends AbstractRoom{
	protected PdkRoomInfo pdkRoomInfo;
	protected int curwhosTurn = -1;
	protected String diZhuId;
	protected int bombNum;
	protected transient int noQiangNum;
	protected transient String lastUserId;
	protected transient PdkHand lastOutHand;
	protected transient String winUserId;
	protected transient PdkPlayBack playback;
	protected transient long curhowsTurnStartTime;
	
	public PdkRoom(String ownId) {
		super(CardContants.GAMETYPE_Pdk, ownId);
		this.curwhosTurn = new Random().nextInt(getMaxUserNum());
		this.pdkRoomInfo = new PdkRoomInfo();
	}
	
	@Override
	public void doTimedTask() {
		super.doTimedTask();
		if(state == RoomState.NoPeopleQiang) {
			if(getChangeStateTime() > 2*GameConstants.SECOND) {
				setState(RoomState.Running);
				startGame();
			}
		}
	}

	@Override
	public void addPlayer(BasePlayer player) {
		synchronized (this.playerList) {
			if(this.playerList.size()<getMaxUserNum()) {
				player.setTableIndex(this.playerList.size());
				super.addPlayer(player);
				//通知所有人房间信息改变
				sendRoomInfo();
				return;
			}
		}
	}
	//跑得快出牌前合法判断
	public void handOut(PdkPlayer player,Vector<Card> cards) {
		PdkHand hand = new PdkHand(cards);
		if(!hand.isRegular()
				|| !player.isContains(cards)
				|| 
				(hand.isPass() 
						&& (lastUserId == null 
						|| StringUtil.equals(lastUserId, player.getUserId())))
				|| 
				(lastOutHand != null 
					&& !StringUtil.equals(this.lastUserId, player.getUserId()) 
					&& !hand.isPass() 
					&& hand.compareTo(this.lastOutHand) <= 0)) {
			sendUpdateCards(player);
			broadChuPai();
			return;
		}
		if(!hand.isPass()) {
			player.removeCards(cards);
		}
		broadHandOut(player, hand);
		player.pdkInfo.setLastOutHand(hand);
		this.playback.addOutHand(player, hand);
		broadTable(null);
		
		if(hand.isPass()) {
			nextDoPlayer();
			return;
		}
		if(hand.isBomb()) {
			this.bombNum ++;
			player.pdkInfo.addBomb();
		}
		this.lastOutHand = hand;
		this.lastUserId = player.getUserId();
		if(player.isWin()) {
			this.winUserId = player.getUserId();
			sendEnd2Player();
			endGame(); 
			return;
		}
		nextDoPlayer();
	}
	
	public void changeWhoTurn(int nextTurn) {
		this.curwhosTurn = nextTurn;
		this.curhowsTurnStartTime = System.currentTimeMillis();
	}
	
	public void allNotQiang() {
		JsonMessage message = JsonMessage.createMessage(MessageComm.S2C_NoPeopleQiang);
		broadcast(message);
		endGame();
		setState(RoomState.NoPeopleQiang);
	}
	
	public void qiangDizhu(PdkPlayer player,boolean qiang) {
		if(player.isQiang) {
			JsonMessage message = JsonMessage.createMessage(MessageComm.S2C_PdkQiangDizhu);
			message.addProperty("userId", player.getUserId());
			message.addProperty("qiang", qiang?1:0);
			JsonMessageCenter.getInstance().sendMessage(message, player);
			return;
		}
		player.isQiang = true;
		JsonMessage message = JsonMessage.createMessage(MessageComm.S2C_PdkQiangDizhu);
		message.addProperty("userId", player.getUserId());
		message.addProperty("qiang", qiang?1:0);
		broadcast(message);
		
		if(qiang) {
			setState(RoomState.Running);
			this.playback.setDiZhuId(this.diZhuId);
			this.diZhuId = player.getUserId();
			changeWhoTurn(player.getTableIndex());
//			broadDiPai();
//			player.addDiPai(pdkRoomInfo.getDiPai());
			sendUpdateCards(player);
			broadChuPai();
		}else{
			noQiangNum++;
			if(noQiangNum == 3) {
				allNotQiang();
				return;
			}
			nextDoPlayer();
		}
	}
	
	public void nextDoPlayer() {
		changeWhoTurn(getNextPlayer());
		if(!StringUtil.NullOrEmpty(this.lastUserId)) {
			PdkPlayer player = getPlayerByTableIndex(this.curwhosTurn);
			if(StringUtil.equals(this.lastUserId, player.getUserId())) {
				this.lastUserId = null;
				this.lastOutHand = null;
			}
		}
		broadChuPai();
	}
	//解散房间
	@Override
	public void disbandRoom() {
		if(isStartGame) {
			calAllGame(true);
		}else{
			JsonMessage message = JsonMessage.createMessage(MessageComm.S2C_RoomDisband);
			message.addProperty("firstId", ownerId);
			broadcast(message);
			clearRoom();
		}
	}
	@Override
	public void disbandAgencyRoom() {
		if(isStartGame) {
			calAllGame(true);
		}else{
			JsonMessage message = JsonMessage.createMessage(MessageComm.S2C_DisbandAgencyCreateRoom);
			message.addProperty("firstId", ownerId);
			broadcast(message);
			clearRoom();
		}
	}
	public void clearData() {
		this.noQiangNum = 0;
		this.diZhuId = null;
		setState(RoomState.End);
	}
	
	public void sendEnd2Player() {
		PdkPlayer winPlayer = getPlayerById(this.winUserId);
		boolean isDzWin = StringUtil.equals(this.diZhuId, this.winUserId);
		int bombNum = Math.min(this.bombNum, getMaxBomb());
//		boolean isChunTian = isDzWin?isNMChunTian():getPlayerById(this.diZhuId).pdkInfo.getOutSize()<=1;
//		int score = (int)Math.pow(2, bombNum);
		int score = 2 + bombNum*2;
//		if(isChunTian) score *= 2;
		List<PdkResult> resultList = Lists.newArrayList();
		
		UserBack ub = new UserBack(this);
		for (int i = this.playerList.size()-1; i >= 0; i--) {
			PdkPlayer player = (PdkPlayer)playerList.get(i);
			int tempScore = score; 
			int playersore1;
			int playersore2;
			if(player.getHandSize() == 0) {
				if (i+1 == 3) {
					PdkPlayer templayer1= (PdkPlayer)playerList.get(0);
					playersore1 = templayer1.getHandSize();
				}else {
					PdkPlayer templayer1= (PdkPlayer)playerList.get(i+1);
					playersore1 = templayer1.getHandSize();
				}
				
				if (i-1 == -1) {
					PdkPlayer templayer1= (PdkPlayer)playerList.get(2);
					playersore2 = templayer1.getHandSize();
				}else {
					PdkPlayer templayer1= (PdkPlayer)playerList.get(i-1);
					playersore2 = templayer1.getHandSize();
				}
				tempScore = score*2 + playersore1+playersore2;
			}else{
				tempScore = -score - player.getHandSize();
			}
			player.pdkInfo.calGame(tempScore);
			PdkResult result = new PdkResult(player, tempScore);
			resultList.add(result);
			ub.addScore(player.nickName, tempScore);
		}
		
		JsonMessage message = JsonMessage.createMessage(MessageComm.S2C_Pdk_GAME_END);
		message.addProperty("results", resultList);
		message.addProperty("playNum", playNum);
		message.addProperty("isDzWin", isDzWin);
//		message.addProperty("isChunTian", isChunTian);
		message.addProperty("bombNum", this.bombNum);
		message.addProperty("curBei", (int)Math.pow(2, bombNum));
		message.addProperty("lastOutUserId", this.lastUserId);
		message.addProperty("lastOutCard", this.lastOutHand);
		broadcast(message);
		if(!isMatchRoom()) {
			this.playback.setResultList(resultList);
			this.playback.setDiZhuId(diZhuId);
//			this.playback.setDiPai(Lists.newArrayList(pdkRoomInfo.getDiPai()));
			PlayBackManager.getInstance().savePlayback(playback, this, ub);
		}
	}
	public PdkPlayer getPlayerById(String userId) {
		return (PdkPlayer)super.getPlayerById(userId);
	}
	public PdkPlayer getPlayerByTableIndex(int index) {
		return (PdkPlayer)super.getPlayerByTableIndex(index);
	}
	
	public boolean isEndGame() {
		return this.playNum >= roomSetting.getMaxPlayNum();
	}
	
	@Override
	public void endGame() {
		super.endGame();
		PdkPlayer winPlayer = getPlayerById(this.winUserId);
		this.curwhosTurn = winPlayer.getTableIndex();
		this.bombNum = 0;
		this.diZhuId = null;
		this.lastUserId = null;
		this.lastOutHand = null;
		this.winUserId = null;
		clearData();
		if(isEndGame()) {
			calAllGame(false);
			return;
		}
	}
	
	public void calAllGame(boolean isDisband) {
		List<PdkAllResult> resultList = Lists.newArrayList();
		for (int i = this.playerList.size()-1; i >= 0; i--) {
			PdkPlayer player = (PdkPlayer)playerList.get(i);
			resultList.add(new PdkAllResult(player, this.playNum));
		}
		JsonMessage message = JsonMessage.createMessage(MessageComm.S2C_Pdk_ALL_END);
		System.out.println("调用的是跑得快的游戏结束calAllGame方法S2C_Pdk_ALL_END");
		message.addProperty("resultList", resultList);
		if(isDisband) {
			message.addProperty("isDisband", 1);
		}
		broadcast(message);
		clearRoom();
	}
	
	public void broadHandOut(PdkPlayer player,PdkHand hand) {
		JsonMessage message = JsonMessage.createMessage(MessageComm.S2C_PdkHandOut);
		message.addProperty("userId", player.getUserId());
		message.addProperty("handSize", player.getHandSize());
		message.addProperty("outHand", hand);
		broadcast(message);
	}
	public void broadTable(BasePlayer temp) {
		List<PdkInfo> pdkInfoList = Lists.newArrayList();
		for (BasePlayer p : getPlayerList()) {
			PdkPlayer player = (PdkPlayer)p;
			pdkInfoList.add(player.pdkInfo);
		}
		JsonMessage message = JsonMessage.createMessage(MessageComm.S2C_PdkTable);
		message.addProperty("pdkInfoList", pdkInfoList);
		message.addProperty("curBei", (int)Math.pow(2, this.bombNum));
		if(temp != null) {
			JsonMessageCenter.getInstance().sendMessage(message, temp);
		}else{
			broadcast(message);
		}
	}
	
	public void broadChuPai() {
		broadChuPai(null);
	}
	//出牌
	public void broadChuPai(BasePlayer temp) {
		JsonMessage message = JsonMessage.createMessage(MessageComm.S2C_ChuPai);
		message.addProperty("curwhosTurn", curwhosTurn);
		if(state == RoomState.QiangDizhu) {
			message.addProperty("isQiang", true);
		}else{
			message.addProperty("isQiang", false);
			message.addProperty("lastUserId", lastUserId);
			message.addProperty("lastOutHand", lastOutHand);
		}
		if(temp != null) {
			JsonMessageCenter.getInstance().sendMessage(message, temp);
		}else{
			broadcast(message);
		}
		
		
		
		
		
		
		
		
		
		
	}
/*	public void broadDiPai() {
		JsonMessage message = JsonMessage.createMessage(MessageComm.S2C_PdkDiPai);
		message.addProperty("diPai", pdkRoomInfo.getDiPai());
		message.addProperty("diZhuId", this.diZhuId);
		message.addProperty("curwhosTurn", curwhosTurn);
		broadcast(message);
	}*/
	//开始跑得快游戏
	@Override
	public void startGame() {
		this.playNum++;
		super.startGame();
//		setState(RoomState.QiangDizhu);
		Vector<Card> tableCards = CardUtils.createPdk();
//		Vector<Card> diPai = CardUtils.faPaiToVector(tableCards, 3);
		System.err.println("===========开始游戏:"+tableCards.size()+"===================");
//		this.pdkRoomInfo.setDiPai(diPai);
//		System.err.println("===========底牌:"+GSONUtils.ToJSONString(diPai)+"===================");
		for (int i = 0; i < playerList.size(); i++) {
			PdkPlayer player = (PdkPlayer)playerList.get(i);
			Vector<Card> outCard = CardUtils.faPaiToVector(tableCards, 16);
			// 查询红桃3在谁手里，因为红桃3先出牌
			for (Card card : outCard) {
				if (card.getType() == 1 && card.getIndex() ==3) {
//					player.isQiang = true;
					changeWhoTurn(player.getTableIndex());
				}
			}
			//玩家初始化手中的牌
			player.initCards(outCard);
			System.err.println("===========发牌:"+player.getHandSize()+"===================");
			//向客户端发送开始游戏
			sendStartGame(player);

		}
		System.err.println("===========开始游戏完毕:"+tableCards.size()+"===================");
		this.playback = new PdkPlayBack(this);
		this.curhowsTurnStartTime = System.currentTimeMillis();
		
		broadChuPai();
	}
	public void sendUpdateCards(PdkPlayer player) {
		JsonMessage message = new JsonMessage(MessageComm.S2C_HandUpdate2Out);
		message.addProperty("hand", player.cards);
		message.addProperty("curwhosTurn", curwhosTurn);
		JsonMessageCenter.getInstance().sendMessage(message, player);
	}
	public void sendStartGame(PdkPlayer player) {
		JsonMessage message = new JsonMessage(MessageComm.S2C_StartGame);
		message.addProperty("hand", player.cards);
		JsonMessageCenter.getInstance().sendMessage(message, player);
	}
	public int getNextPlayer() {
        return curwhosTurn == getMaxUserNum() - 1 ? 0 : curwhosTurn + 1;
    }

	@Override
	public int getMaxUserNum() {
		return 3;
	}
	
	public int getMaxBomb() {
		return Integer.MAX_VALUE;
	}
	public boolean isDiZhu(String userId) {
		return StringUtil.equals(this.diZhuId, userId);
	}
	public boolean isNMChunTian() {
		for (BasePlayer basePlayer : playerList) {
			PdkPlayer p = (PdkPlayer)basePlayer;
			if(!StringUtil.equals(diZhuId, p.getUserId())) {
				if(p.pdkInfo.getOutSize() > 0) return false;
			}
		}
		return true;
	}
	
	@Override
	public void breakConnect(BasePlayer p) {
		PdkPlayer player = (PdkPlayer)p;
		JsonMessage message1 = new JsonMessage(MessageComm.C2S_BreakConnect);
		message1.addProperty("room", this);
		JsonMessageCenter.getInstance().sendMessage(message1, player);
		if(isStartGame) {
			sendUpdateCards(player);
			broadTable(player);
			broadChuPai(player);
			if(this.state == RoomState.DisbandRequest) {
				sendDisandRoomRequest();
			}
		}
		player.changeOnline(true);
	}
	
	public static void main(String[] args) {
		System.err.println((int)Math.pow(2, 3));
	}
}
